#!/usr/bin/python2.4
#
# Copyright 2010 Google Inc.

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Stores and provides the metadata for tests.

Stores and provides the data regarding the tests. The Aggregate
object contains meta-data per test - duration (cost in time),
pass and fail count (failure history). The purpose of this object
is to fascilitate an easy transfer of the metadata.

DataSource stores the collected information so that the optimisation
algorithm can easily access them. The contents are initialised using
the Initialise method, which takes the following:
1) tests : a list of test target names
2) matrix : a list of numpy.ndarrays that describes the coverage relation
3) metadata : a dictionary that maps test target names to Aggregate
   objects - refer to sponge_dremel module for Aggregate object

"""

__author__ = 'ntrolls@gmail.com (Shin Yoo), robni@google.com (Robert Nilsson)'

import csv
import numpy


class Aggregate(object):
  def __init__(self):
    self.duration = 0
    self.pass_count = 0
    self.fail_count = 0
    self.tap = False

  def __repr__(self):
    return "%d, %d, %s" % (self.duration, self.pass_count, self.tap)

  def Update(self, user, status, duration):
    total = (self.pass_count + self.fail_count)
    self.duration = (self.duration * total + duration) / (total + 1)
    if status == 'FAILED':
      self.fail_count += 1
    else:
      self.pass_count += 1
    if user=='tap-prod':
      self.tap = True

  def Update2(self, user, status, count, sum_duration):
    total = (self.pass_count + self.fail_count)
    self.duration = (self.duration * total + sum_duration) / (total + count)
    if status == 'FAILED':
      self.fail_count += count
    else:
      self.pass_count += count
    if user == 'tap-prod':
      self.tap = True


class DataSource(object):
  """Stores and provides information about tests."""

  def __init__(self):
    ##names of the test targets
    self.testnames = []

    ## trace stores coverage type data as a list of numpy.ndarrays
    self.traces = []
    self.costs = []
    ## number of passed executions and total executions in history
    self.passed = []
    self.executed = []
    ## numberoftests is the number of test targets; numberoftargets
    ## is the number of library targets in the cone
    self.numberoftests = 0
    self.numberoftargets = 0
    self.filetraces = []

  def InitialiseWithCSVFiles(self, conedatafilename, metadatafilename):
    """Initialises the self based on the given filenames."""
    self.testnames = []
    self.traces = []
    self.costs = []
    self.passed = []
    self.executed = []
    self.filetraces = []
    self.numberoftests = 0
    self.numberoftargets = 0

    self.ReadTraces(conedatafilename)
    self.ReadMetaData(metadatafilename)

  def Initialise(self, tests, matrix, metadata):
    """Initialises the self baed on the given objects."""
    self.testnames = tests
    self.numberoftests = len(tests)
    self.traces = matrix
    self.numberoftargets = len(matrix[0])
    self.costs = []
    self.passed = []
    self.executed = []
    for i in xrange(len(tests)):
      test = tests[i]
      aggregate = metadata[test]
      self.costs.append(aggregate.duration / 1000)
      self.passed.append(aggregate.pass_count)
      self.executed.append(aggregate.pass_count + aggregate.fail_count)
    print matrix

  def ReadTraces(self, filename):
    """Reads coverage from csv file; rows are tests, columns are covered entities."""
    tracefile = open(filename, 'r')
    lines = tracefile.readlines()
    self.numberoftests = int(lines[0])
    self.numberoftargets = int(lines[1])
    for line in lines[2:]:
      a = numpy.array([int(x) for x in line.split(',')], dtype=bool)
      self.traces.append(a)

  def ReadMetaData(self, filename):
    """Reads basic metadata from csv file; name, cost, # passed, # executed."""
    metadatafile = open(filename, 'r')
    reader = csv.reader(metadatafile, delimiter=',')
    for row in reader:
      self.testnames.append(row[0])
      self.costs.append(float(row[1]))
      self.passed.append(int(row[2]))
      self.executed.append(int(row[3]))
